package org.budo.zookeeper.curator.util;

import java.util.concurrent.TimeUnit;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.budo.support.spring.context.aware.BudoApplicationContextAware;

import lombok.extern.slf4j.Slf4j;

/**
 * @author limingwei
 */
@Slf4j
public class InterProcessLockUtil {
    private static CuratorFramework getCuratorFramework() {
        return BudoApplicationContextAware.getBeanCached(CuratorFramework.class);
    }

    public static boolean acquireInSeconds(String lockPath, Number seconds) {
        CuratorFramework curatorFramework = getCuratorFramework();
        InterProcessLock interProcessLock = new InterProcessMutex(curatorFramework, lockPath);
        return acquire(interProcessLock, seconds.longValue(), TimeUnit.SECONDS);
    }

    public static void releaseQuietly(String lockPath) {
        CuratorFramework curatorFramework = getCuratorFramework();
        InterProcessLock interProcessLock = new InterProcessMutex(curatorFramework, lockPath);
        releaseQuietly(interProcessLock);
    }

    public static void releaseQuietly(InterProcessLock interProcessLock) {
        try {
            if (!interProcessLock.isAcquiredInThisProcess()) {
                log.info("#16 not acquiredInThisProcess, interProcessLock=" + interProcessLock);
                return;
            }

            interProcessLock.release();
        } catch (Throwable e) {
            log.error("#17 interProcessLock.release error, e=" + e, e);
        }
    }

    public static boolean acquire(InterProcessLock interProcessLock, long time, TimeUnit unit) {
        try {
            return interProcessLock.acquire(time, unit);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}